﻿//Trade.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.BusinessEntities
{
	using System;
	using System.Collections.Generic;
	using System.ComponentModel;
	using System.Runtime.Serialization;
	using System.Xml.Serialization;

	using Ecng.Common;
	using Ecng.ComponentModel;
	using Ecng.Serialization;

	/// <summary>
	/// Тиковая сделка.
	/// </summary>
	[Serializable]
	[System.Runtime.Serialization.DataContract]
	[DisplayName("Сделка")]
	[Description("Тиковая сделка.")]
	public class Trade : Equatable<Trade>, IExtendableEntity
	{
		/// <summary>
		/// Создать <see cref="Trade"/>.
		/// </summary>
		public Trade()
		{
		}

		/// <summary>
		/// Идентификатор сделки.
		/// </summary>
		[DataMember]
		[DisplayName("Идентификатор")]
		[Description("Идентификатор сделки.")]
		[Category("Основные")]
		[Identity]
		public long Id { get; set; }

		/// <summary>
		/// Инструмент, по которому была совершена сделка.
		/// </summary>
		[RelationSingle(IdentityType = typeof(string))]
		[XmlIgnore]
		[Browsable(false)]
		public Security Security { get; set; }

		/// <summary>
		/// Время совершения сделки.
		/// </summary>
		[DataMember]
		[DisplayName("Время")]
		[Description("Время совершения сделки.")]
		[Category("Основные")]
		public DateTime Time { get; set; }

		/// <summary>
		/// Задержка в получении информации о сделке.
		/// </summary>
		[DataMember]
		[DisplayName("Задержка")]
		[Description("Задержка в получении информации о сделке.")]
		[Category("Основные")]
		[Ignore]
		public TimeSpan Latency { get; set; }

		/// <summary>
		/// Количество контрактов в сделке.
		/// </summary>
		[DataMember]
		[DisplayName("Объем")]
		[Description("Количество контрактов в сделке.")]
		[Category("Основные")]
		public decimal Volume { get; set; }

		/// <summary>
		/// Цена сделки.
		/// </summary>
		[DataMember]
		[DisplayName("Цена")]
		[Description("Цена сделки.")]
		[Category("Основные")]
		public decimal Price { get; set; }

		/// <summary>
		/// Направление заявки (покупка или продажа), которая привела к сделке.
		/// </summary>
		[DataMember]
		[Nullable]
		[DisplayName("Направление")]
		[Description("Направление заявки (покупка или продажа), которая привела к сделке.")]
		[Category("Основные")]
		public OrderDirections? OrderDirection { get; set; }

		private bool _isSystem = true;

		/// <summary>
		/// Является ли сделка системной.
		/// </summary>
		[DataMember]
		[DisplayName("Системная сделка")]
		[Description("Является ли сделка системной.")]
		[Category("Основные")]
		public bool IsSystem
		{
			get { return _isSystem; }
			set { _isSystem = value; }
		}

		/// <summary>
		/// Системный статус сделки.
		/// </summary>
		[Browsable(false)]
		public int Status { get; set; }

		/// <summary>
		/// Количество открытых позиций (открытый интерес).
		/// </summary>
		[DataMember]
		[DisplayName("Открытый интерес")]
		[Description("Количество открытых позиций (открытый интерес).")]
		[Category("Основные")]
		public decimal OpenInterest { get; set; }

		[field: NonSerialized]
		private IDictionary<object, object> _extensionInfo;

		/// <summary>
		/// Расширенная информация по сделке.
		/// </summary>
		/// <remarks>
		/// Необходима в случае хранения в программе дополнительной информации, ассоциированной со сделкой.
		/// Например, операция, преведшая к сделке.
		/// </remarks>
		[Ignore]
		[XmlIgnore]
		[DisplayName("Расширенная информация")]
		[Description("Необходима в случае хранения в программе дополнительной информации, ассоциированной со сделкой.")]
		[Category("Основные")]
		public IDictionary<object, object> ExtensionInfo
		{
			get { return _extensionInfo; }
			set { _extensionInfo = value; }
		}

		[field: NonSerialized]
		private PropertyChangedEventHandler _propertyChanged;

		event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
		{
			add { _propertyChanged += value; }
			remove { _propertyChanged -= value; }
		}

		void INotifyPropertyChangedEx.NotifyPropertyChanged(string info)
		{
			_propertyChanged.SafeInvoke(this, info);
		}

		/// <summary>
		/// Создать копию объекта <see cref="Trade"/>.
		/// </summary>
		/// <returns>Копия объекта.</returns>
		public override Trade Clone()
		{
			return new Trade
			{
				Id = Id,
				Volume = Volume,
				Price = Price,
				Time = Time,
				Latency = Latency,
				OrderDirection = OrderDirection,
				Security = Security,
				IsSystem = IsSystem,
				Status = Status,
				OpenInterest = OpenInterest,
			};
		}

		/// <summary>
		/// Проверить сделки на эквивалентность.
		/// </summary>
		/// <param name="other">Другая сделка, с которой необходимо сравнивать.</param>
		/// <returns>True, если сделки равны, иначе, false.</returns>
		public override bool Equals(Trade other)
		{
			// ускоренный метод - переопределяем Equatable<T>.Equals, медленный - OnEquals
			return ReferenceEquals(this, other);
		}

		/// <summary>
		/// Рассчитать хеш-код объекта <see cref="Trade"/>.
		/// </summary>
		/// <returns>Хеш-код.</returns>
		public override int GetHashCode()
		{
			return (Security != null ? Security.GetHashCode() : 0) ^ Id.GetHashCode();
		}

		/// <summary>
		/// Получить строковое представление.
		/// </summary>
		/// <returns>Строковое представление.</returns>
		public override string ToString()
		{
			return "{0} {1} {2} {3}".Put(Time, Id,Price, Volume);
		}
	}
}